package cn.hinglo.common.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.jfinal.upload.UploadFile;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.Date;

/**
 * @createTime: 2019/7/19 : 17:07
 * @author: HingLo
 * @description: 文件上传工具类
 */
@Slf4j
public class UploadKit {

    /***
     * 保存的路径
     */
    private static final String FILE_PATH = PropertiesKit.get("filePath");
    /***
     * 文件服务器的域名
     */
    private static final String FILE_URL = PropertiesKit.get("fileUrl");


    /***
     * 图片后缀
     */
    private static final String[] IMG_SUFFIX = PropertiesKit.getToStringArray("imgSuffix");

    /***
     * 文件后缀支持
     */
    private static final String[] FILE_SUFFIX = PropertiesKit.getToStringArray("fileSuffix");


    /***
     * 文件上传
     * @param data 文件数据流
     * @param type 文件类型，用于分类文件夹
     * @param fileName 文件名称
     * @return 返回结果
     */
    private static String uploadFile(byte[] data, String fileName, String type) {
        suffixFileValidate(fileName);
        if (StrUtil.isBlank(fileName)) {
            throw new RuntimeException("文件名称不能为空");
        }
        if (StrUtil.isBlank(type)) {
            throw new RuntimeException("文件类型为必须参数,用于区分文件类型");
        }
        String filePath = type + "/" + DateUtil.format(new Date(), "yyyyMMdd") + "/" + fileName;
        try {
            FileUtil.writeBytes(data, FILE_PATH + filePath);
            return filePath;
        } catch (Exception e) {
            log.error("文件保存失败,失败信息为:", e);
            throw e;
        }

    }

    /***
     * 上传文件
     * @param uploadFile Jfinal上传的文件对象
     * @return 返回结果
     */
    public static String uploadFile(UploadFile uploadFile, String type) {
        if (uploadFile != null) {
            String originalFileName = uploadFile.getOriginalFileName();
            String fileName = SecureUtil.md5(uploadFile.getFile()) + originalFileName.substring(originalFileName.lastIndexOf("."));
            return uploadFile(FileUtil.readBytes(uploadFile.getFile()), fileName, type);
        }
        throw new RuntimeException("上传文件对象为空,请检查上传方式是否正确");
    }

    /***
     * 带有文件名称的文件上传
     * @param uploadFile 文件上传对象
     * @param fileName 文件名称
     * @return 返回文件名称
     */
    public static String uploadFile(UploadFile uploadFile, String fileName, String type) {
        if (uploadFile != null && StrUtil.isNotBlank(fileName)) {
            return uploadFile(FileUtil.readBytes(uploadFile.getFile()), fileName, type);
        }
        throw new RuntimeException("上传文件对象为空,请检查上传方式是否正确");
    }

    /***
     * 带有文件名称的文件上传
     * @param file 文件对象
     * @param fileName 文件名称
     * @return 返回文件名称
     */
    public static String uploadFile(File file, String fileName, String type) {
        if (file != null && StrUtil.isNotBlank(fileName)) {
            return uploadFile(FileUtil.readBytes(file), fileName, type);
        }
        throw new RuntimeException("上传文件对象为空,请检查上传方式是否正确");
    }

    /***
     * 文件上传
     * @param file 文件对象
     * @return 返回文件名称
     */
    public static String uploadFile(File file, String type) {
        if (file != null) {
            String originalFileName = file.getName();
            String fileName = SecureUtil.md5(file) + originalFileName.substring(originalFileName.lastIndexOf("."));
            return uploadFile(FileUtil.readBytes(file), fileName, type);
        }
        throw new RuntimeException("上传文件对象为空,请检查上传方式是否正确");
    }

    /***
     * 图片上传
     * @param uploadFile 图片的文件对象
     * @return 返回保存路径
     */
    public static String uploadImage(UploadFile uploadFile, String type) {
        suffixImgValidate(uploadFile.getFileName());
        return uploadFile(uploadFile, type);
    }

    /***
     * 图片后缀校验
     * @param imgName 图片名称
     * @return 返回是否是图片
     */
    private static void suffixImgValidate(String imgName) {
        boolean contains = ArrayUtil.contains(IMG_SUFFIX, imgName.toUpperCase());
        if (!contains) {
            throw new RuntimeException(StrUtil.format("不支持该图片类型,请上传%s格式图片", ArrayUtil.join(IMG_SUFFIX, ",")));
        }
    }

    /***
     * 文件后缀校验
     * @param fileName 文件名称
     * @return 返回是否是允许上传的文件后缀
     */
    private static void suffixFileValidate(String fileName) {
        boolean contains = ArrayUtil.contains(FILE_SUFFIX, fileName.toUpperCase());
        if (!contains) {
            throw new RuntimeException("不支持该文件类型上传");
        }
    }


    /***
     * 返回文件后缀
     * @param name 文件名称
     * @return 返回后缀
     */
    private static String getSuffix(String name) {
        return name.substring(name.lastIndexOf("."));
    }

    /***
     * 校验文件是否是指定的后缀
     * @param uploadFile 文件上传对象
     * @param suffix 后缀
     * @return 返回结果
     */
    public static boolean checkFileSuffix(UploadFile uploadFile, String suffix) {
        if (uploadFile == null || StrUtil.isBlank(suffix)) {
            return false;
        }
        return suffix.equals(getSuffix(uploadFile.getOriginalFileName()));

    }

    /***
     * 校验文件是否是指定的后缀
     * @param file 文件对象
     * @param suffix 后缀
     * @return 返回结果
     */
    public static boolean checkFileSuffix(File file, String suffix) {
        if (file == null || StrUtil.isBlank(suffix)) {
            return false;
        }
        return suffix.equals(getSuffix(file.getName()));
    }


    /***
     * 文件下载访问的绝对路径(该链接一般为公有链接不做权限验证，使用Nginx做静态资源返回)
     * @param filePath 文件路径
     * @return 返回结果
     */
    public static String getFileUrl(String filePath) {
        return FILE_URL + filePath;
    }

    /***
     * 获取文件全路径
     * @param filePath 相对路径
     * @return 返回结果
     */
    public static String getFilePath(String filePath) {
        return FILE_PATH + filePath;
    }
}
